package com.jfirer.validator.path;

import java.util.Iterator;
import javax.validation.Path;
import javax.validation.ValidationException;
import com.jfirer.validator.path.api.ConnectionNode;

public class PathImpl implements Path
{
    private final NodeEntry head;
    
    public PathImpl(ConnectionNode connectionNode)
    {
        NodeEntry head = null;
        while (connectionNode != null)
        {
            Node node = connectionNode.asNode();
            NodeEntry nodeEntry = new NodeEntry();
            nodeEntry.next = head;
            nodeEntry.node = node;
            head = nodeEntry;
            connectionNode = connectionNode.pred();
        }
        this.head = head;
    }
    
    @Override
    public Iterator<Node> iterator()
    {
        Iterator<Node> iterator = new Iterator<Path.Node>() {
            
            NodeEntry head = PathImpl.this.head;
            
            @Override
            public boolean hasNext()
            {
                return head != null;
            }
            
            @Override
            public Node next()
            {
                Node node = head.node;
                head = head.next;
                return node;
            }
            
            @Override
            public void remove()
            {
                throw new UnsupportedOperationException();
            }
        };
        return iterator;
    }
    
    @Override
    public String toString()
    {
        StringBuilder cache = new StringBuilder();
        Iterator<Node> tmp = iterator();
        while (tmp.hasNext())
        {
            Node node = tmp.next();
            if (node.isInIterable() == false)
            {
                if (cache.length() == 0)
                {
                    if (node.getName() != null)
                    {
                        cache.append(node.getName());
                    }
                }
                else
                {
                    if (node.getName() != null)
                    {
                        cache.append('.').append(node.getName());
                    }
                }
            }
            else
            {
                if (node.getIndex() != null)
                {
                    cache.append('[').append(node.getIndex()).append(']');
                }
                else if (node.getKey() != null)
                {
                    cache.append('[').append(node.getKey()).append(']');
                }
                else
                {
                    throw new ValidationException(new NullPointerException());
                }
            }
        }
        return cache.toString();
    }
    
    class NodeEntry
    {
        Node      node;
        NodeEntry pred;
        NodeEntry next;
    }
    
}
